#ifndef SWEGL_RENDER_VERTEX_H
#define SWEGL_RENDER_VERTEX_H

#include "swegl/common.h"
#include "swegl/math.h"

namespace swegl
{

struct RenderVertex
{
	Vec3 viewspacePos;
	Vec4 screenspacePos;
	uint8 clipFlags;
	uint8 _padding[3];
	// todo: align structure on 32 bit to keep gradients (floats) 32 bit aligned
};

class RenderVertexFormat
{
public:
	RenderVertexFormat();

	sint normalOffset;
	sint diffuseOffset;
	sint specularOffset;
	sint textureOffset;
	uint numGradients;

	uint vertexSize;
};

inline RenderVertexFormat::RenderVertexFormat()
{
	normalOffset = -1;
	diffuseOffset = -1;
	specularOffset = -1;
	textureOffset = -1;
	numGradients = 0;

	vertexSize = sizeof(RenderVertex);
}

class RenderVertexArray
{
public:
	RenderVertexArray();
	~RenderVertexArray();

	// allocate memory, size is in byte
	void allocate(size_t size);
	// set the current vertex size
	void setVertexSize(size_t size);

	RenderVertex *operator [](size_t index);
	const RenderVertex *operator [](size_t index) const;

	size_t numVertices() const;
	void setNumVertices(size_t numVertices);
	RenderVertex *insert();

private:
	size_t m_vertexSize;
	size_t m_numVertices;
	size_t m_bufferSize;
	uint8 *m_data;
};

inline RenderVertexArray::RenderVertexArray() : m_vertexSize(0), m_numVertices(0), m_bufferSize(0), m_data(0)
{
}

inline RenderVertexArray::~RenderVertexArray()
{
	delete [] m_data;
}

inline void RenderVertexArray::allocate(size_t size)
{
	delete [] m_data;
	m_data = new uint8[size];
	m_bufferSize = size;
}

inline void RenderVertexArray::setVertexSize(size_t size)
{
	m_vertexSize = size;
}

inline RenderVertex *RenderVertexArray::operator [](size_t index)
{
	return reinterpret_cast<RenderVertex *>(m_data + index * m_vertexSize);
}

inline const RenderVertex *RenderVertexArray::operator [](size_t index) const
{
	return reinterpret_cast<const RenderVertex *>(m_data + index * m_vertexSize);
}

inline size_t RenderVertexArray::numVertices() const
{
	return m_numVertices;
}

inline void RenderVertexArray::setNumVertices(size_t numVertices)
{
	sweglAssert(numVertices * m_vertexSize <= m_bufferSize);
	m_numVertices = numVertices;
}

inline RenderVertex *RenderVertexArray::insert()
{
	sweglAssert((m_numVertices + 1) * m_vertexSize <= m_bufferSize);
	return reinterpret_cast<RenderVertex *>(m_data + m_numVertices++ * m_vertexSize);
}

}

#endif 
